/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.dataset.r3000;

import java.util.*;
import java.io.*;
import java.net.Socket;

import javax.net.SocketFactory;

public class R3000DataClient {

	public static void main(String[] args) {
		int failCount = 0;
		try {

			String host = null;
			File builtFile = null;
			File logDir = null;
			int sensorID = -1;
			String logID = null;

			try {
				host = args[0];
				builtFile = new File(args[1]);
				if (!builtFile.exists())
					throw new Exception("Specified build file does not exist.");
				logDir = new File(args[2]);
				if (!logDir.exists() || !logDir.isDirectory())
					throw new Exception(
							"Specified log directory does not exist.");
				sensorID = Integer.parseInt(args[3]);
				logID = args[4];
			} catch (Exception e) {
				System.out.println(e.getMessage());
				System.out
						.println("Usage: java R3000DataClient host built_list log_dir sensor_id r3000_log_id");
				return;
			}

			while (true) {

				Vector<String> temp = new Vector<String>();
				LineNumberReader in = new LineNumberReader(new FileReader(
						builtFile));
				String line = in.readLine();
				while (line != null) {
					if (line.length() >= 8) {
						temp.addElement(line);
					}
					line = in.readLine();
				}
				in.close();

				R3000Entry[] entries = new R3000Entry[temp.size() + 1];
				for (int i = 0; i < entries.length - 1; i++) {
					entries[i] = new R3000Entry((String) temp.elementAt(i));
					// System.out.println(entries[i]);
				}
				// Arrays.sort(entries);

				GregorianCalendar end = (GregorianCalendar) Calendar
						.getInstance();
				end.set(Calendar.YEAR, 2004);
				end.set(Calendar.MONTH, 0);
				end.set(Calendar.DAY_OF_MONTH, 1);
				String endStr = "20050701";
				String startStr = "20150101";

				GregorianCalendar cal = (GregorianCalendar) Calendar
						.getInstance();
				cal.setTimeInMillis(System.currentTimeMillis());
				// cal.set(Calendar.MONTH, 6);
				// cal.set(Calendar.DAY_OF_MONTH, 1);
				// cal.set(Calendar.YEAR, 2006);

				String calStr = "" + cal.get(Calendar.YEAR);
				int month = cal.get(Calendar.MONTH) + 1;
				if (month < 10)
					calStr += "0";
				calStr += month;
				int day = cal.get(Calendar.DAY_OF_MONTH);
				if (day < 10)
					calStr += "0";
				calStr += day;
				boolean didSomething = false;
				while (calStr.compareTo(endStr) >= 0) {
					// while ((calStr.compareTo(endStr) >= 0) &&
					// (calStr.compareTo(startStr) <= 0)) {
					// System.out.println("NOW:" + calStr);
					if (didSomething) {
						Thread.sleep(10000);
						break;
					}
					boolean found = false;
					for (int i = 0; i < entries.length; i++) {
						if (entries[i] != null) {
							// System.out.println(entries[i].getDateString() + "
							// <-> " + calStr);
							if (entries[i].getDateString().compareTo(calStr) == 0) {
								// check each run
								for (int x = 1; x <= 24; x++) {
									if ((entries[i].bitMap & (int) Math.pow(2,
											x)) == (int) (Math.pow(2, x))) {
										// System.out.println("Indexed run #" +
										// x);
									} else {
										// System.out.println("Need to index run
										// #" + x);
										File[] files = logDir
												.listFiles(new R3000FileFilter(
														cal, x, logDir, logID));
										if ((files != null)
												&& (files.length != 0)) {
											String filePath = files[0]
													.getAbsolutePath();
											int m = entries[i].cal
													.get(Calendar.MONTH) + 1;
											int d = entries[i].cal
													.get(Calendar.DAY_OF_MONTH);
											int y = entries[i].cal
													.get(Calendar.YEAR);

											int val = processFile(filePath,
													host, entries[i].cal, x,
													sensorID);
											System.out
													.println("Processing returned with code "
															+ val);
											if (val < 0) {
												System.out
														.println("Failed to process file: '"
																+ filePath
																+ "'");
												failCount++;
												if (failCount > 10) {
													System.out
															.println("Exiting due to too many errors.");
													System.exit(1);
												}

											} else {
												didSomething = true;
												entries[i].bitMap += (long) Math
														.pow(2, x);
											}
										} else {
											// System.out.println("No file
											// found.");
										}
										break;
									}
								}
								found = true;
								break;
							}

						}
					}
					if (!found) {
						// System.out.println("Need to create new Entry for " +
						// cal.getTime());
						R3000Entry e = new R3000Entry();
						// e.cal = new GregorianCalendar();
						e.cal.setTimeInMillis(cal.getTimeInMillis());
						entries[entries.length - 1] = e;
					} else {
						cal.set(Calendar.DAY_OF_MONTH, cal
								.get(Calendar.DAY_OF_MONTH) - 1);
						calStr = "" + cal.get(Calendar.YEAR);
						month = cal.get(Calendar.MONTH) + 1;
						if (month < 10)
							calStr += "0";
						calStr += month;
						day = cal.get(Calendar.DAY_OF_MONTH);
						if (day < 10)
							calStr += "0";
						calStr += day;
					}
				}

				PrintWriter out = new PrintWriter(new FileWriter(args[1]));
				for (int i = 0; i < entries.length; i++) {
					if ((entries[i] != null) && (entries[i].bitMap > 0)) {
						out.println(entries[i]);
						// System.out.println(entries[i]);
					}
				}
				out.close();

			}
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	private static int processFile(String filePath, String host,
			GregorianCalendar cal, int run, int sensorID) {
		try {
		    System.out.println("R3000 agent processing " + filePath);
			SocketFactory sf = SocketFactory.getDefault();
			Socket s = sf.createSocket(host, 9097);
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			DataInputStream dis = new DataInputStream(s.getInputStream());
			dos.writeInt(sensorID); // sensor ID
			dos.writeInt(1); // insert
			dos.writeInt(1); // distributed
			dos.writeInt(1); // self
			dos.writeInt(1);
			dos.writeInt(cal.get(Calendar.MONTH) + 1);
			dos.writeInt(cal.get(Calendar.DAY_OF_MONTH));
			dos.writeInt(cal.get(Calendar.YEAR));
			dos.writeInt(run);

			LineNumberReader in = new LineNumberReader(new FileReader(filePath));
			String line = in.readLine();
			while (line != null) {
				dos.writeInt(line.length());
				dos.writeBytes(line);
				line = in.readLine();
			}
			in.close();
			dos.writeInt(-1);
			return dis.readInt();
		} catch (Exception E) {
			E.printStackTrace();
		}
		return -1;
	}

}
